﻿using System;
using System.Collections.Generic;
using System.Data.Objects;
using System.Linq;
using System.Reactive;
using System.Reactive.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
using Microsoft.Practices.Unity;

namespace Sern.Common
{
    public class EfObjectContextInjectionFactory<TContext> : InjectionFactory
            where TContext : ObjectContext
    {
        private static readonly IDictionary<string, ObjectContext> contextCache = new Dictionary<string, ObjectContext>();

        public EfObjectContextInjectionFactory(string connectionString) :
            base(
                c =>
                {

                    var transactionKey = Transaction.Current.TransactionInformation.LocalIdentifier;
                    if (!contextCache.ContainsKey(transactionKey))
                    {
                        var entityContainer = Activator.CreateInstance(typeof(TContext), new object[] { connectionString }) as TContext;
                        contextCache.Add(transactionKey, entityContainer);
                        Observable.FromEventPattern<TransactionCompletedEventHandler, TransactionEventArgs>(
                            handler => Transaction.Current.TransactionCompleted += handler,
                            handler => Transaction.Current.TransactionCompleted -= handler)
                        .Subscribe(
                            Observer.Create<EventPattern<TransactionEventArgs>>(
                                _ =>
                                {
                                    if (_.EventArgs.Transaction.TransactionInformation.Status == TransactionStatus.Committed)
                                    {
                                        contextCache[_.EventArgs.Transaction.TransactionInformation.LocalIdentifier].SaveChanges();
                                    }
                                    contextCache.Remove(_.EventArgs.Transaction.TransactionInformation.LocalIdentifier);
                                })
                        );
                    }
                    return contextCache[transactionKey];
                }
            )
        {
        }
    }
}
